// Copyright (c) 2010, Anthony Cassidy
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification, are 
// permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice, this list 
//         of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice, this 
//         list of conditions and the following disclaimer in the documentation and/or 
//         other materials provided with the distribution.
//     * Neither the name of the AntsAdventureGameCreator nor the names of its contributors 
//         may be used to endorse or promote products derived from this software without 
//         specific prior written permission.
// 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
// THE POSSIBILITY OF SUCH DAMAGE.
#include "XStdafx.h"
#include "XRoomObject.h"
#include "XGlobals.h"
#include "RoomRegistry.h"
#include "XAnimation.h"
#include "XAnimations.h"
#include "XHitType.h"
#include "AntsApi_NoDependencies.h"
#include "IXMainWindowMethodsXRoomNeeds.h"

#include "XDiagnostics.h"



XRoomObject::XRoomObject(QString keyword, IXMainWindowMethodsXRoomNeeds& p)
: m_keyword(keyword)
, m_fak(keyword)
, m_result(0)
, m_callback(p)
{
    m_talkingColor = "green";
    m_isVisible = true;
    m_top = 0;
    m_left = 0;
    m_talkingAnimation = "";
    m_anims = new XAnimations(); // del in destructor
    m_isCurrentAnimRepeatingWhilstVisible = false;
    m_talkingDelay = 0;
    m_currentTimerId = 0;
    m_orderingNumber = 0;
    m_isGiveEnabled = false; 
}
XRoomObject::~XRoomObject()
{
    XDiagnostics::Delete("XRoomObject");
    delete m_anims;
}
QColor ColorFromString(QString color)
{
    color = color.toUpper();
    if(color == "WHITE")
    {
        return Qt::white;
    }
    else if(color == "RED")
    {
        return Qt::red;
    }
    else if(color == "GREEN")
    {
        return Qt::green;
    }
    else if(color == "BLUE")
    {
        return Qt::blue;
    }
    else if(color == "LIGHTBLUE"  || color == "CYAN")
    {
        return Qt::cyan;
    }
    else if(color == "LIGHTBLUE"  || color == "CYAN")
    {
        return Qt::cyan;
    }
    else if(color == "DARKCYAN")
    {
        return Qt::darkCyan;
    }
    else if(color == "PURPLE"  || color == "MAGENTA")
    {
        return Qt::magenta;
    }
    else if(color == "YELLOW")
    {
        return Qt::yellow;
    }
    else if(color == "GRAY"  || color == "LIGHTGRAY")
    {
        return Qt::lightGray;
    }
    /*
    color0,
    color1,
    black,
    white,
    darkGray,
    gray,
    lightGray,
    red,
    green,
    blue,
    cyan,
    magenta,
    yellow,
    darkRed,
    darkGreen,
    darkBlue,
    darkCyan,
    darkMagenta,
    darkYellow,
    */


    return Qt::white;
}

void XRoomObject::AddAnimation(QString keyword, QString fullPath)
{
    QPointer<XAnimation> anim = new XAnimation(this, keyword);// del in destructor
    anim->AddAllFramesInFolder(fullPath);
    m_anims->Add(anim);
}

void XRoomObject::SetFullPath(QString folder)
{ 
    // add the first frame in the folder as the default "anim".
    m_anims->Clear();
    if(QDir(folder).exists())
    {
        QStringList pngFiles = QDir(folder).entryList(QStringList(QString("*.png")));
        if(pngFiles.count())
        {
            for(int i=0;i<pngFiles.count();i++)
            {
                if(pngFiles.at(i).length())
                {
                    // add the first frame in the folder as the default "anim"
                    QPointer<XAnimation> anim = new XAnimation(this, "(defaultanim)");// del in destructor
                    anim->GetFrames().Add(folder + "/" + pngFiles.at(i));
                    anim->SetKeyword("(defaultanim)");
                    m_anims->Add(anim);
                    break;
                }
            }

            // load defaultimage from m_subFolder
            if(m_anims->Count())
            {
                SetCurrentImageFilename(m_anims->At(0)->GetFrames().At(0));
            }else
            {
                Log::Images(QString("No Animations (all blank) for %1 %2 %3").arg(Keyword()).arg(m_fak.AnimName()).arg(m_fak.Frame()));
            }
        }else
        {
            Log::Images(QString("No Animations(pngFiles is empty) for %1 %2 %3").arg(Keyword()).arg(m_fak.AnimName()).arg(m_fak.Frame()));
        }
    }else
    {
        Log::Images(QString("No Animations(folder %1 not exist) for %2 %3 %4").arg(folder).arg(Keyword()).arg(m_fak.AnimName()).arg(m_fak.Frame()));
    }


}


void XRoomObject::SetTalkingAnimationName(QString speechAnim)
{
    m_talkingAnimation = speechAnim;
}

void XRoomObject::Say(QString speech)
{
    KillCurrentAnimationAndClearInstructions();
    m_speech = speech;
    Log::Animation(QString("Speech set to %1").arg(speech));
    m_fak.SetAnimName( m_talkingAnimation );
    m_fak.SetFrame(0);
    int framesOfTalking = AntsApi::SpeechToFrames(speech);

    for(int i=0;i<framesOfTalking;i++)
    {
        m_instructions.push_back("INC");
    }

    int id = startTimer(AntsApi::GetMillisecondsPerTick()+m_talkingDelay);
    (id=id);
}


void XRoomObject::SayWithoutAnimation(QString speech)
{
    m_speech = speech;
    m_fak.SetAnimName( m_talkingAnimation );
    int id = startTimer(AntsApi::SpeechToFrames(speech)*AntsApi::GetMillisecondsPerTick());
    KillCurrentAnimationAndClearInstructions();
    (id=id);
}
void DumpInstructions(std::deque<QString> list)
{
    for(unsigned int i=0;i<list.size();i++)
    {
        Log::InstructionList(QString(" %1").arg(list.at(i)));
    }
}

void XRoomObject::KillCurrentAnimationAndClearInstructions()
{

    if(m_instructions.size()>0)
    {
        //QMessageBox::warning(NULL, "warning", QString("Animation cut off by %1 frames").arg(m_timerTicksRemaining));
        Log::Animation(QString("Animation cut off by %1 frames").arg(m_instructions.size()));
        killTimer(m_currentTimerId);
        SetBlocking(false);//any time we kill the timer
        m_instructions.clear();
    }
}

void XRoomObject::PlayAnimation(QString animationKeyword, int delay, int isRepeat, int isBackward, int isHoldOnLastFrame)
{
    KillCurrentAnimationAndClearInstructions();



    m_instructions.push_front(animationKeyword);
    m_instructions.push_front(isBackward? "LAST" : "FIRST");

    QPointer<XAnimation>& anim = m_anims->At(animationKeyword);
    for(int i=0;i<anim->GetFrames().Count()-1;i++)
    {
        m_instructions.push_front(isBackward? "DEC" : "INC");
    }

    if(!isHoldOnLastFrame)
    {
        m_instructions.push_front("normal");
    }

    DumpInstructions(m_instructions);

    NextInstruction();
    UpdateImage();

    m_isCurrentAnimRepeatingWhilstVisible = isRepeat;

    m_currentTimerId = startTimer(AntsApi::GetMillisecondsPerTick()+delay);
    Log::Images(QString("Starting animation %1 delay:%2 delay+mspertick:%3").arg(m_currentTimerId).arg(delay).arg(AntsApi::GetMillisecondsPerTick()));
    // Log::Images(QString("Progress to next frame of [%1] which is %2 / %3 %4").arg(m_fak.AnimName()).arg(m_fak.Frame()).arg(anim->GetFrames().Count()-1).arg( m_anims->At(m_fak.AnimName())->GetFrames().At(m_fak.Frame())));
}

void XRoomObject::PlayAnimationHoldLastFrame(QString animationKeyword, int delay)
{
    PlayAnimation(animationKeyword,delay,0,0,true);
}

void XRoomObject::PlayAnimationRepeatWhilstVisible(QString animationKeyword, int delay)
{
    PlayAnimation(animationKeyword,delay,true,0,0);
}


void XRoomObject::PlayAnimationBackwards(QString animationKeyword, int delay)
{
    PlayAnimation(animationKeyword,delay,0,true,0);
}

void XRoomObject::PlayAnimationBackwardsHoldLastFrame(QString animationKeyword, int delay)
{
    PlayAnimation(animationKeyword,delay,0,true,true);
}

void XRoomObject::GotoFirstFrame()
{
    m_fak.SetFrame(0);
}

void XRoomObject::GotoLastFrame()
{
    QPointer<XAnimation>& anim = m_anims->At(m_fak.AnimName());
    m_fak.SetFrame(anim->GetFrames().Count()-1);
}

void XRoomObject::IncrementFrame()
{
    QPointer<XAnimation>& anim = m_anims->At(m_fak.AnimName());
    // Log::Images(QString("Progress to next frame of [%1] which is %2 / %3 %4").arg(m_fak.AnimName()).arg(m_fak.Frame()).arg(anim->GetFrames().Count()-1).arg( m_anims->At(m_fak.AnimName())->GetFrames().At(m_fak.Frame())));

    int i = m_fak.Frame() +1;
    if(i >=anim->GetFrames().Count())
    {
        m_fak.SetFrame(0);
    }else
    {
        m_fak.SetFrame(i);
    }
    // do no update image here - since it is a heavy operation, we do it once per tick.
}

void XRoomObject::DecrementFrame()
{
    QPointer<XAnimation>& anim = m_anims->At(m_fak.AnimName());
    // Log::Images(QString("Progress to next frame of [%1] which is %2 / %3 %4").arg(m_fak.AnimName()).arg(m_fak.Frame()).arg(anim->GetFrames().Count()-1).arg( m_anims->At(m_fak.AnimName())->GetFrames().At(m_fak.Frame())));

    int i = m_fak.Frame() -1;
    if(i <0)
    {
        m_fak.SetFrame(anim->GetFrames().Count()-1);
    }else
    {
        m_fak.SetFrame(i);
    }
    // do no update image here - since it is a heavy operation, we do it once per tick.
}

void XRoomObject::NextInstruction()
{
    ASSERT(m_instructions.size());
    while(m_instructions.size())
    {
        QString ins = m_instructions.back();
        m_instructions.pop_back();

        if(ins == "INC")
        {
            IncrementFrame();
            break;
        }
        else if (ins == "DEC")
        {
            DecrementFrame();
            break;
        }
        else if (ins == "DECX")
        {
            SetX( X() -1 );
        }
        else if( ins == "DECY")
        { 
            SetY( Y() -1 );
        }
        else if (ins == "INCX")
        {
            SetX( X() +1 );
        }
        else if( ins == "INCY")
        { 
            SetY( Y() +1 );
        }
        else if(ins == "FIRST")
        {
            GotoFirstFrame();
            break;
        }
        else if(ins == "LAST")
        {
            GotoLastFrame();
            break;
        }
        else
        {
            m_fak.SetAnimName(ins);

        }

    }
}

void XRoomObject::timerEvent(QTimerEvent* timer)
{
    try{

        if(m_instructions.size()<=0)\
        {
            if(m_isCurrentAnimRepeatingWhilstVisible && m_isVisible)
            {
                Log::Images("Not killing because repeat whilst visible is true");
                IncrementFrame();
            }
            else
            {
                Log::Images(QString("Killing timer %1").arg(timer->timerId()));
                killTimer(timer->timerId());
                SetBlocking(false);//any time we kill the timer
                m_speech = "";
            }
            // no update here. returning the image to 'normal' is for the next redraw.
        }else
        {

            NextInstruction();
        }
        Log::Images(QString("About to update.. id:%1").arg(timer->timerId()));
        UpdateImage();// if I don't include this, then image will get set to frame zero of wrong animation

    }
    catch(std::exception)
    {
    }

}

void XRoomObject::UpdateImage()
{
    XAnimationFrameCollection& frames = m_anims->At(m_fak.AnimName())->GetFrames();

    // These are controversial, because it will make people scripts rely
    // on the previously executed action to determine whether it is
    // starting at Zero (would be  the case if we set frame to zero during every setToNormal)
    // or whether it will be starting at the last frame in an animation.
    // It means that those scenes wanting non-hold-on-last frame calls to actually
    // reset to zero, should have normal animation set to 1 frame.
    // 
    // Need to bring p the improtance of 'normal animation in the docs.
    if(m_fak.Frame() >= frames.Count())
    {
        m_fak.SetFrame( frames.Count() -1);
    }
    else if(m_fak.Frame() <0)
    {
        m_fak.SetFrame( 0);
    }
    QString filename = frames.At(m_fak.Frame());
    SetCurrentImageFilename(filename);
}



void XRoomObject::SetCurrentImageFilename(QString currentImageFilename)
{
    ASSERT(QFile::exists(currentImageFilename) && "tried to set current image with a dud filename");

    QString pngAsBmp = currentImageFilename;

    if(m_map.find(currentImageFilename) != m_map.end())
    {
        m_image = m_map[currentImageFilename];
        Log::Images(QString("Set current filename image to [%1] cached ").arg( m_anims->At(m_fak.AnimName())->GetFrames().At(m_fak.Frame())));
    }
    else if(QFile::exists(currentImageFilename))
    {
        Log::Images(QString("Set current filename image to [%1] NON-CACHED").arg( m_anims->At(m_fak.AnimName())->GetFrames().At(m_fak.Frame())));

        m_currentImageFilename = currentImageFilename;
        bool isLoaded = m_image.Load(m_currentImageFilename, qRgb(XHitType::Object, m_index,0));
        (isLoaded = isLoaded);
        m_map[m_currentImageFilename] = m_image;
        ASSERT(isLoaded && "SetCurrentImage failed to load the file, corrupt file?");
    }

}


void XRoomObject::DrawIfVisible(QPainter& displayPainter, QPainter& zbufferPainter, QRgb zbufferColor, bool showDot, bool showBox)
{
    Q_UNUSED(zbufferColor);
    if(!m_image.IsNull() && IsVisible())
    {
        m_image.DrawImage(displayPainter, m_left, m_top);
        m_image.DrawZBuffer(zbufferPainter, m_left, m_top);

        if(showDot)
        {
            QPoint p = GetMiddleOfBase(m_fak.AnimName());
            displayPainter.drawPoint(p.x(), p.y());
            displayPainter.drawPoint(p.x(), p.y()+1);
            displayPainter.drawPoint(p.x()+1, p.y());
            displayPainter.drawPoint(p.x()+1, p.y()+1);
        }
        if(showBox)
        {
            displayPainter.drawRect(m_image.Rect() );
        }
    }
}

void XRoomObject::DrawSpeechIfVisible(QPainter& painter)
{
    Log::Animation(QString("Speech Drawn %1").arg(m_speech));

    if(m_speech.length())
    {
        // if normal mode, draw text in blue.
        // the strategy for harry's dialog

        // The choices font is always be arial to fit on one line
        // Also use arial here too..
        // so it is obvious that what is on screen is what's just been chosen
        QFont font("arial");

        // Will it still be obvious if we increase the size? 
        //font.setPointSize(10);
        painter.setFont(font);
        painter.setPen(Qt::black);

        QRect parentRect = m_parent->rect();
        QRect speechRect = parentRect.adjusted(20,20,0,0);// give it a margin
        speechRect.intersect(parentRect);

        // draw it once in black and get resultant rect
        QRect resultantRect;
        painter.drawText(speechRect, Qt::TextWordWrap, m_speech, &resultantRect);

        // draw it four more times, using the same width and height (so word wrap doesn't change)
        // could use a rect and adjust it four times, but easier to use x,y,w,h method
        int x = resultantRect.x();
        int y = resultantRect.y();
        int width = resultantRect.width();
        int height = resultantRect.height();
        painter.drawText(x+1, y, width, height, Qt::TextWordWrap, m_speech);
        painter.drawText(x-1, y, width, height, Qt::TextWordWrap, m_speech);
        painter.drawText(x, y+1, width, height, Qt::TextWordWrap, m_speech);
        painter.drawText(x, y-1, width, height, Qt::TextWordWrap, m_speech);
        //added these because dark cyan was hard to see
        painter.drawText(x+1, y+1, width, height, Qt::TextWordWrap, m_speech);
        painter.drawText(x-1, y+1, width, height, Qt::TextWordWrap, m_speech);
        painter.drawText(x+1, y-1, width, height, Qt::TextWordWrap, m_speech);
        painter.drawText(x-1, y-1, width, height, Qt::TextWordWrap, m_speech);

        // draw text fro speech color
        painter.setPen(ColorFromString(m_talkingColor));
        painter.drawText(resultantRect, Qt::TextWordWrap, m_speech);
    }
}

void XRoomObject::PreloadAnimation(QString animKeyword)
{
    QPointer<XAnimation> xanim = Animations()->At(animKeyword);
    for(int i = 0;i<xanim->GetFrames().Count();i++)
    {
        QString frameImageFilename = xanim->GetFrames().At(i);
        if(m_map.find(frameImageFilename) != m_map.end())
            continue;

        QRgb zbufferColor = qRgb(XHitType::Object,i,0);

        XImage image;
        bool isLoaded = image.Load(frameImageFilename, zbufferColor);
        if(isLoaded)
        {
            m_map[frameImageFilename] = image;
            Log::Images(QString("Preloading %1").arg(animKeyword));
        }
        if(!isLoaded)
        {
            Log::Images(QString("Could not load file %1:%s").arg(animKeyword).arg(frameImageFilename));
            ASSERT(isLoaded && "SetCurrentImage failed to load the file, corrupt file?");
        }
    }
}


void XRoomObject::SetCurrentAnimationName(QString animKeyword)
{ 
    m_anims->At(animKeyword);
    m_fak.SetAnimName(animKeyword);
    UpdateImage();
}

QString XRoomObject::CurrentAnimName()
{ 
    return m_fak.AnimName();
}

void XRoomObject::SetCurrentAnimationFrameIndex(int frame)
{ 
    m_fak.SetFrame(frame);
    UpdateImage();
}

int XRoomObject::GetCurrentAnimationFrameIndex() const 
{
    Log::WaitForFrame(QString("%1 %2)").arg(Keyword()).arg(m_fak.Frame()));
    return m_fak.Frame();
}

QString XRoomObject::GetDisplayName()
{ 
    return m_displayName;
}
void XRoomObject::SetDisplayName(QString displayName)
{ 	
    m_displayName = displayName;
}

QString XRoomObject::Keyword() const
{ 
    return m_keyword;
}

void XRoomObject::SetTalkingDelay(int i)
{
    m_talkingDelay = i;
}

void XRoomObject::SetX(int x)
{ 
    m_left = x;
}
void XRoomObject::SetY(int y)
{ 
    m_top = y;
}
int XRoomObject::X()
{ 
    return m_left;
}
int XRoomObject::Y()
{ 
    return m_top;
}

QPoint XRoomObject::GetMiddleOfBase(QString animKeyword)
{
    PreloadAnimation(animKeyword);

    int minLeft = 1000;
    int maxRight = 0;
    int maxBottom = 0;
    QPointer<XAnimation> xanim = Animations()->At(animKeyword);
    for(int i = 0;i<xanim->GetFrames().Count();i++)
    {
        QString filename = xanim->GetFrames().At(i);
        XImage img = m_map[filename];
        QRect rect = img.Rect();

        if(rect.left() < minLeft)
            minLeft = rect.left();
        if(rect.right() > maxRight)
            maxRight = rect.right();
        if(rect.bottom() > maxBottom)
            maxBottom = rect.bottom();
    }

    return QPoint(m_left + (minLeft +maxRight)/2, m_top + maxBottom);
}

void XRoomObject::WalkTo(int destinationX, int destinationY)
{
    KillCurrentAnimationAndClearInstructions();
    QPoint currentPoint = GetMiddleOfBase("normal");

    int xPixels = abs(destinationX-currentPoint.x());
    int yPixels = abs(destinationY-currentPoint.y());
    QMessageBox m; 

    if( xPixels > yPixels)
    {
        QString instruction = "";
        if(destinationX<currentPoint.x())
        {
            QString walkHorizontalLeft = m_specialAnimations[West];
            m_instructions.push_front(walkHorizontalLeft);
            instruction = "DECX";
        }
        else
        {
            QString walkHorizontalRight = m_specialAnimations[East];
            m_instructions.push_front(walkHorizontalRight);
            instruction = "INCX";
        }
        float y = 0.0;
        int lastY= 0;
        float yinc = (destinationY-currentPoint.y())* 1.0/xPixels;
        for(int x=0;x< xPixels; x++, y+=yinc)
        {
            if(int(y) > lastY)//has to be bigger, can't be equals
            {
                m_instructions.push_front("INCY");
                lastY = int(y);
            }
            else if(int(y) < lastY)
            {
                m_instructions.push_front("DECY");
                lastY = int(y);
            }
            m_instructions.push_front(instruction);
            m_instructions.push_front("INC");
        }
    }
    else 
    {
        QString instruction = "";
        if(destinationY<currentPoint.y())
        {
            QString walkHorizontalUp = m_specialAnimations[North];
            m_instructions.push_front(walkHorizontalUp);
            instruction = "DECY";
        }else
        {
            QString walkHorizontalDown = m_specialAnimations[South];
            m_instructions.push_front(walkHorizontalDown);
            instruction = "INCY";
        }

        float x = 0.0;
        int lastX= 0;
        float xinc = (destinationX-currentPoint.x())* 1.0/yPixels;
        for(int y=0;y< yPixels; y++, x+=xinc)
        {
            if(int(x) > lastX)//has to be bigger, can't be equals
            {
                m_instructions.push_front("INCX");
                lastX = int(x);
            }
            else if(int(x) < lastX)
            {
                m_instructions.push_front("DECX");
                lastX = int(x);
            }
            m_instructions.push_front(instruction);
            m_instructions.push_front("INC");

        }
    }
    m_instructions.push_front("normal");
    m_instructions.push_front("FIRST");

    int delay = 0;
    m_currentTimerId = startTimer(AntsApi::GetMillisecondsPerTick()+delay);
    Log::Images(QString("Starting animation %1 delay:%2 delay+mspertick:%3").arg(m_currentTimerId).arg(delay).arg(AntsApi::GetMillisecondsPerTick()));

}

void XRoomObject::SetSpecialAnimation(SpecialAnimation a, QString animKeyword)
{
    // TODO a check whether keyword is valid...but need an ContainsKey() method.
    m_specialAnimations[a] = animKeyword;
}


void XRoomObject::DoChoices(Choices choices)
{
    m_callback.DoChoices(choices, *this);
}


void XRoomObject::SetParentWidget(QWidget* widget)
{
    m_parent = widget;
}

int XRoomObject::GetResult()
{
    return m_result;
}

QPoint XRoomObject::BaseMiddle()
{
    // TODO. make get middle of base const
    QPoint currentPoint = GetMiddleOfBase("normal");
    return currentPoint;
}

void XRoomObject::SetTalkingColor(QString color)
{
    m_talkingColor = color;
}

void XRoomObject::SetOrderingNumber(int orderingNumber)
{
    m_orderingNumber = orderingNumber;
    m_callback.UpdateRoomObjectOrder();
}

int XRoomObject::OrderingNumber() const
{ 
    return m_orderingNumber;
}

void XRoomObject::SetChoicesResult(int result)
{
    m_callback.SetDisallowInput(true);
    m_result = result;
}

void XRoomObject::SetEnableGive(bool isGiveEnabled)
{
    m_isGiveEnabled = isGiveEnabled;
}

bool XRoomObject::IsGiveEnabled()
{
    return m_isGiveEnabled;
}
void XRoomObject::SetIndex(int i)
{ 
    m_index = i;
}


QPointer<XAnimations>& XRoomObject::Animations()
{ 
    return m_anims; 
}

QString XRoomObject::GetSpeech()
{ 
    return m_speech;
}

void XRoomObject::SetVisible(bool visible)
{ 	
    m_isVisible = visible;
}

bool XRoomObject::IsVisible()
{ 
    return m_isVisible;
}


QString XRoomObject::GetCurrentImageFilename() const
{ 
    return m_currentImageFilename;
}
